#include "StdAfx.h"
#include "MovableObject.h"

///////////////////////////////////////////////////////////////////////////
// Default constructor - creates a new movable object and places it
// at (0,0,0)
///////////////////////////////////////////////////////////////////////////
MovableObject::MovableObject()
{
	position = Ogre::Vector3::ZERO;
}

///////////////////////////////////////////////////////////////////////////
// Create a new movable object located at the specified position
///////////////////////////////////////////////////////////////////////////
MovableObject::MovableObject(Ogre::Vector3 pos)
{
	position = pos;
}

MovableObject::~MovableObject(void)
{
}

///////////////////////////////////////////////////////////////////////////
// Move the object one space to the left. Returns false if we cannot
// move
///////////////////////////////////////////////////////////////////////////
bool MovableObject::MoveLeft(GameLevel& level, bool force=false)
{
	// calculate the position we want to move to
	Ogre::Vector3 newPosition = position;
	newPosition.x--;

	// make sure it is still in bounds
	if( newPosition.x < 0.0 )
	{
		throw new std::exception("Cannot move object left - already at zero");
	}

	// make sure nothing is blocking the spot we want to move to
	if( (! force) && IsBlocked(level, newPosition) )
	{
		return false;
	}

	//
	// okay, all good. Commit the new position, and let the caller know
	// that it worked
	//
	position = newPosition;

	return true;
}

///////////////////////////////////////////////////////////////////////////
// Move the object one space to the right. Returns false if we cannot
// move
///////////////////////////////////////////////////////////////////////////
bool MovableObject::MoveRight(GameLevel& level, bool force=false)
{
	// calculate the position we want to move to
	Ogre::Vector3 newPosition = position;
	newPosition.x++;

	// make sure its within level boundaries
	if( newPosition.x > level.Width() -1 )
	{
		throw new std::exception("Cannot move object right - would move past level bound");
	}

	// make sure nothing is blocking the spot we want to move to
	if( (! force) && IsBlocked(level, newPosition) )
	{
		return false;
	}

	//
	// okay, all good. Commit the new position, and let the caller know
	// that it worked
	//
	position = newPosition;

	return true;
}

///////////////////////////////////////////////////////////////////////////
// Move the object one space up. Returns false if we cannot move
///////////////////////////////////////////////////////////////////////////
bool MovableObject::MoveUp(GameLevel& level, bool force=false)
{
	// calculate the position we want to move to
	Ogre::Vector3 newPosition = position;
	newPosition.y--;

	// make sure its within level boundaries
	if( newPosition.y < 0.0 )
	{
		throw new std::exception("Cannot move object up - would move past level bound");
	}

	// make sure nothing is blocking the spot we want to move to
	if( (! force) && IsBlocked(level, newPosition) )
	{
		return false;
	}

	//
	// okay, all good. Commit the new position, and let the caller know
	// that it worked
	//
	position = newPosition;

	return true;
}

///////////////////////////////////////////////////////////////////////////
// Move the object one space down. Returns false if we cannot move
///////////////////////////////////////////////////////////////////////////
bool MovableObject::MoveDown(GameLevel& level, bool force=false)
{
	// calculate the position we want to move to
	Ogre::Vector3 newPosition = position;
	newPosition.y++;

	// make sure its within level boundaries
	if( newPosition.y > level.Height() - 1 )
	{
		throw new std::exception("Cannot move object down - would move past level bound");
	}

	// make sure nothing is blocking the spot we want to move to
	if( (! force) && IsBlocked(level, newPosition) )
	{
		return false;
	}

	//
	// okay, all good. Commit the new position, and let the caller know
	// that it worked
	//
	position = newPosition;

	return true;	
}

///////////////////////////////////////////////////////////////////////////
// Checks if the specified position is actually blocked by another object
// RETURN: True if there is no block
///////////////////////////////////////////////////////////////////////////
bool MovableObject::IsBlocked(GameLevel& level, Ogre::Vector3 pos)
{
	//
	// defer the question to the level
	//
	return level.IsSpaceOccupied(pos);
}
